package com.example.myplayer;

import android.media.MediaCodec;
import android.media.MediaFormat;
import android.util.Log;
import android.view.Surface;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;

public class H264Player implements Runnable{
    MediaCodec mediaCodec;
    String path;
    Surface surface;
    public H264Player(Surface surface, String path){
        this.surface = surface;
        this.path = path;
        try {
            mediaCodec = MediaCodec.createDecoderByType("video/avc");
            MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 368, 384);
            mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
            mediaCodec.configure(mediaFormat, surface, null, 0);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
        Log.e("77777777777777", "H264Player run: ");

        mediaCodec.start();
        try {
            byte[] bytes = getH264Bytes(path);

            ByteBuffer[] byteBuffers = mediaCodec.getInputBuffers();
            int startIndex = 0;
            int totalSize = bytes.length;
            for (;;){

                if (totalSize == 0 || startIndex >= totalSize){
                    break;
                }

                int nextFrameStartIndex = findFrameStart(bytes, startIndex, totalSize);
                Log.e("77777777777777", "H264Player6354  "+bytes[nextFrameStartIndex + 4] +" nextFrameStartIndex ="+nextFrameStartIndex);
                if (bytes[nextFrameStartIndex + 4] == 0x67 ||
                        bytes[nextFrameStartIndex + 4] == 0x68 ||
                        bytes[nextFrameStartIndex + 4] == 0x06) {
                    Log.e("77777777777777", "H264Player2  "+bytes[nextFrameStartIndex + 4]);
                    continue;
                }

                Log.e("77777777777777", "2222222" );
                MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
                int inIndex = mediaCodec.dequeueInputBuffer(1000);

                if (inIndex >= 0){

                    ByteBuffer byteBuffer = byteBuffers[inIndex];
                    byteBuffer.clear();
                    Log.e("77777777777777", "startIndex = "+startIndex +" nextFrameStartIndex = "+nextFrameStartIndex);

                    byteBuffer.put(bytes, startIndex, nextFrameStartIndex - startIndex);

                    mediaCodec.queueInputBuffer(inIndex, 0, nextFrameStartIndex - startIndex, 0, 0);
                    startIndex = nextFrameStartIndex;

                } else {
                    continue;
                }

                int outIndex = mediaCodec.dequeueOutputBuffer(info, 1000);
                if (outIndex >= 0){
                    Thread.sleep(1 / 25);
                    mediaCodec.releaseOutputBuffer(outIndex, true);
                }
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private int findFrameStart(byte[] bytes, int startIndex, int totalSize) {
        Log.e("77777777777777", "H264Player findFrameStart " + "bytes[0]="+bytes[0]+" bytes[1]="+bytes[1]+" bytes[2]="+bytes[2]+" bytes[3]="+bytes[3]);
        int j = 0;
        for (int i = startIndex; i < totalSize; i++){
            if (bytes[i] == 0x00 && bytes[i+1] == 0x00 && bytes[i+2] == 0x00 && bytes[i+3] == 0x01){
                return i;
            }
        }
        return -1;
    }

    private byte[] getH264Bytes(String path) throws IOException {
        InputStream inputStream = new DataInputStream(new FileInputStream(new File(path)));

        byte[] bytes = new byte[1024];
        int size = 1024;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        int len = 0;
        while((len=inputStream.read(bytes, 0, size)) != -1){
            bos.write(bytes, 0, len);
        }

        return bytes;
    }
}
